﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AddIn.EA.Framework.Common;

namespace AddIn.EA.Framework
{
    /// <summary>
    /// Class that represent a list of packages.
    /// </summary>
    public class PackageList : BaseList<Package>
    {
        #region Constructors
        /// <summary>
        /// Get a instance of package list.
        /// </summary>
        /// <param name="reference">The reference of EA Object Model package collection.</param>
        public PackageList(EA_Application.Collection reference)
            : this(reference, null) { }
        /// <summary>
        /// Get a instance of package list.
        /// </summary>
        /// <param name="reference">The reference of EA Object Model package collection.</param>
        /// <param name="parent">The parent element.</param>
        public PackageList(EA_Application.Collection reference, IElement parent)
            : base(reference, parent) { }
        #endregion

        #region Public Methods
        /// <summary>
        /// Get a reference of the first package with the package id informed.
        /// </summary>
        /// <param name="id">The package id.</param>
        /// <returns>The object Package found with the same id.</returns>
        public override Package GetReferenceById(int id)
        {
            return GetReferenceById(id, false);
        }
        /// <summary>
        /// Get a reference of the first package with the package id informed in recursive mode.
        /// </summary>
        /// <param name="id">The package id.</param>
        /// <param name="recursive">Flag used to indicate if want to find the package with the same id in child packages case don't find in this list.</param>
        /// <returns>The object Package found with the same id.</returns>
        public Package GetReferenceById(int id, bool recursive)
        {
            Package packageFound = base.GetReferenceById(id);
            if (packageFound == null && recursive)
            {
                foreach (Package package in this)
                {
                    packageFound = package.Packages.GetReferenceById(id, recursive);
                    if (packageFound != null) break;
                }
            }

            return packageFound;
        }
        /// <summary>
        /// Get a reference of the first package with the package name informed.
        /// </summary>
        /// <param name="id">The package name.</param>
        /// <returns>The object Package found with the same name.</returns>
        public override Package GetReferenceByName(string name)
        {
            return GetReferenceByName(name, false);
        }
        /// <summary>
        /// Get a reference of the first package with the package name informed in recursive mode.
        /// </summary>
        /// <param name="id">The package name.</param>
        /// <param name="recursive">Flag used to indicate if want to find the package with the same name in child packages case don't find in this list.</param>
        /// <returns>The object Package found with the same name.</returns>
        public Package GetReferenceByName(string name, bool recursive)
        {
            Package packageFound = base.GetReferenceByName(name);
            if (packageFound == null && recursive)
            {
                foreach (Package package in this)
                {
                    packageFound = package.Packages.GetReferenceByName(name, recursive);
                    if (packageFound != null) break;
                }
            }

            return packageFound;
        }
        #endregion
    }

    /// <summary>
    /// Class that represent a package.
    /// </summary>
    public class Package : BaseElement<EA_Application.Package>
    {
        #region Fields
        private PackageList _packages = null;
        private ElementList _elements = null;
        private Element _element = null;
        #endregion

        #region Constructors
        /// <summary>
        /// Get an instance of package.
        /// </summary>
        /// <param name="reference">The reference of EA Object Model package.</param>
        public Package(EA_Application.Package reference)
            : this(reference, null) { }
        /// <summary>
        /// Get an instance of package.
        /// </summary>
        /// <param name="reference">The reference of EA Object Model package.</param>
        /// <param name="parent">The parent element.</param>
        public Package(EA_Application.Package reference, AddIn.EA.Framework.Common.IElement parent)
            : base(reference, parent) { }
        #endregion

        #region Properties

        #region BaseElement Members
        /// <summary>
        /// The package id.
        /// </summary>
        public override int ID
        {
            get { return this.Reference.PackageID; }
        }
        /// <summary>
        /// The package name.
        /// </summary>
        public override string Name
        {
            get { return this.Reference.Name; }
            set { this.Reference.Name = value; }
        }
        #endregion

        /// <summary>
        /// The path of code generated by EA. Used also to engineering or reengineering code.
        /// </summary>
        public string CodePath
        {
            get { return this.Reference.CodePath; }
            set { this.Reference.CodePath = value; }
        }
        /// <summary>
        /// Flag used to indicate if the package represent a root namespace. Generally used to generate code.
        /// </summary>
        public bool IsNamespaceRoot
        {
            get { return this.Reference.IsNamespace; }
            set { this.Reference.IsNamespace = value; }
        }
        /// <summary>
        /// Flag used to indicate if the package is a model.
        /// </summary>
        public bool IsModel
        {
            get { return this.Reference.IsModel; }
        }
        /// <summary>
        /// Notes of the package.
        /// </summary>
        public string Notes
        {
            get { return this.Reference.Notes; }
            set { this.Reference.Notes = value; }
        }
        /// <summary>
        /// List of child packages.
        /// </summary>
        public PackageList Packages
        {
            get 
            {
                if (_packages == null)
                    _packages = new PackageList(this.Reference.Packages, this);

                return _packages;
            }
        }
        /// <summary>
        /// List of the package elements.
        /// </summary>
        public ElementList Elements
        {
            get 
            {
                if (_elements == null)
                    _elements = new ElementList(this.Reference.Elements, this);

                return _elements;
            }
        }
        /// <summary>
        /// The element related with the package. Used to package documentation using element fields.
        /// </summary>
        public Element Element
        {
            get
            {
                if (_element == null)
                    _element = new Element(this.Reference.Element, this);

                return _element;
            }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Get an element of the package by id.
        /// </summary>
        /// <param name="id">The element id.</param>
        /// <returns>The object Element of the package.</returns>
        public Element GetElementById(int id)
        {
            return this.Elements.GetReferenceById(id);
        }
        /// <summary>
        /// Get an element of the package by name.
        /// </summary>
        /// <param name="name">The package name.</param>
        /// <returns>The object Element of the package.</returns>
        public Element GetElementByName(string name)
        {
            return this.Elements.GetReferenceByName(name);
        }
        /// <summary>
        /// Get a child package by name
        /// </summary>
        /// <param name="name">The package name.</param>
        /// <returns>The object Package.</returns>
        public Package GetPackageByName(string name)
        {
            return this.GetPackageByName(name, false);
        }
        /// <summary>
        /// Get a child package by name in recursive mode.
        /// </summary>
        /// <param name="name">The package name.</param>
        /// <param name="recursive">Flag used to indicate if want to find the package in child packages.</param>
        /// <returns>The object Package.</returns>
        public Package GetPackageByName(string name, bool recursive)
        {
            return this.Packages.GetReferenceByName(name, recursive);
        }
        #endregion
    }
}
